package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.constants.HotArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.mess.ArticleVisitStreamMess;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author brianxia
 * @version 1.0
 * @date 2022-09-27 15:22
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ArticleService {

    @Autowired
    private CacheService cacheService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void hotArticleHandle(ArticleVisitStreamMess mess) {

        //1.更新到数据库
        ApArticle apArticle = updateBehaviorToDb(mess);

        //2.重新计算分值，当天分值 * 3  昨天 1 * 3 = 3分  今天发生2次点赞  1 * 3 + 2 * 3 * 3 = 3 + 18 = 21
        Integer score = computeScore(apArticle) * 3;
        //存历史点赞数和今日点赞数 历史 * 1 + 今日 * 3 得到最新分值 每天跨天的时候使用定时任务xxl-job将今日点赞数搬到历史点赞数中

        //3.更新到redis
        //推荐
        resetArticleScoreInRedis(score,apArticle, HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC + ArticleConstants.DEFAULT_TAG);
        //当前频道
        resetArticleScoreInRedis(score,apArticle, HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC + apArticle.getChannelId());

    }

    private void resetArticleScoreInRedis(Integer score, ApArticle apArticle, String redisKey) {
        String s = cacheService.get(redisKey);
        if(StringUtils.isBlank(s)){
            //没有推荐过文章
            log.error("当前频道没有推荐文章" + apArticle.getChannelId());
            return;
        }

        List<HotArticleVo> articleVos = JSON.parseArray(s, HotArticleVo.class);
        boolean flag = false;
        for (HotArticleVo articleVo : articleVos) {
            if(Objects.equals(apArticle.getId(),articleVo.getId())){
                flag = true;
                articleVo.setScore(score);
                break;
            }
        }

        //不存在
        if(!flag){
            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(apArticle,hotArticleVo);
            hotArticleVo.setScore(score);
            articleVos.add(hotArticleVo);
        }

        List<HotArticleVo> collect = articleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(30).collect(Collectors.toList());
        String s1 = JSON.toJSONString(collect);
        if(!s.equals(s1)){
            cacheService.set(redisKey,s1);
        }

    }

    private Integer computeScore(ApArticle apArticle) {

        Integer score = 0;

        //阅读
        if(apArticle.getViews() != null){
            score += apArticle.getViews() * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }

        if(apArticle.getLikes() != null){
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }


        if(apArticle.getComment() != null){
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }


        if(apArticle.getCollection() != null){
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }


        return score;
    }

    private ApArticle updateBehaviorToDb(ArticleVisitStreamMess mess) {
        //1.创建数据库强制每条数据likes默认初始化为0 ，不要出现null
        //update xxx set  <if like > 0 >likes = likes + 1
        ApArticle apArticle = getById(mess.getArticleId());

        apArticle.setLikes((apArticle.getLikes() == null ? 0 : apArticle.getLikes()) + mess.getLike());
        apArticle.setComment((apArticle.getComment() == null ? 0 : apArticle.getComment()) + mess.getComment());
        apArticle.setViews((apArticle.getViews() == null ? 0 : apArticle.getViews()) + mess.getView());
        apArticle.setCollection((apArticle.getCollection() == null ? 0 : apArticle.getCollection()) + mess.getCollect());

        updateById(apArticle);

        return apArticle;
    }

    public static void main(String[] args) {
        ApArticle apArticle = new ApArticle();

        apArticle.setLikes((apArticle.getLikes() == null ? 0 : apArticle.getLikes()) + 2);

        System.out.println(apArticle);
    }
}
